#include "VulkanApplication.h"
#include <vector>
#include <iostream>

int main(int argc, char** argv)
{
    VulkanApplication app("c07_renderpass", 1024, 768);
    if (!app.initialized())
    {
        printf("Failed to initialize VulkanApplication.\n");
        return 1;
    }

    // Create render-pass
    VkAttachmentDescription colorAttachment
    {
        0, app.getSurfaceFormat().format,
        VK_SAMPLE_COUNT_1_BIT,
        VK_ATTACHMENT_LOAD_OP_CLEAR,       // Load/Store
        VK_ATTACHMENT_STORE_OP_STORE,
        VK_ATTACHMENT_LOAD_OP_DONT_CARE,   // stencilLoad/Store
        VK_ATTACHMENT_STORE_OP_DONT_CARE,
        VK_IMAGE_LAYOUT_UNDEFINED,         // initialLayout
        VK_IMAGE_LAYOUT_PRESENT_SRC_KHR    // finalLayout
    };

    VkAttachmentReference colorAttachmentRef
    {
        0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
    };

    VkSubpassDescription subpass
    {
        0, VK_PIPELINE_BIND_POINT_GRAPHICS,
        0, nullptr,              // pInputAttachments
        1, &colorAttachmentRef,  // pColorAttachments
        nullptr,                 // pResolveAttachments
        nullptr,                 // pDepthStencilAttachment
        0, nullptr,              // pPreserveAttachments
    };

    VkRenderPassCreateInfo renderPassInfo
    {
        VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
        nullptr, 0,
        1, &colorAttachment,  // pAttachments
        1, &subpass,          // pSubpasses
        0, nullptr            // pDependencies
    };
    VkRenderPass renderPass = nullptr;
    VkResult result = vkCreateRenderPass(app.getDevice(), &renderPassInfo, nullptr, &renderPass);
    if (result != VK_SUCCESS)
    {
        printf("Failed to create render-pass.\n");
        return 1;
    }

    // Create framebuffers
    std::vector<VkFramebuffer> framebuffers(app.getSwapchainImageViews().size());
    for (size_t i = 0; i < framebuffers.size(); ++i)
    {
        VkImageView attachments[] = { app.getSwapchainImageViews()[i] };
        VkFramebufferCreateInfo framebufferInfo
        {
            VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
            nullptr, 0,
            renderPass,
            1, attachments,
            1024, 768, 1
        };
        vkCreateFramebuffer(app.getDevice(), &framebufferInfo, nullptr, &framebuffers[i]);
    }

    // Main loop
    VkFence waitFence = app.getOrCreateFence("CommandFence");
    VkSemaphore waitNextImage = app.getOrCreateSemaphore("WaitNextImage");
    VkSemaphore waitSubmission = app.getOrCreateSemaphore("WaitSubmission");
    VkCommandBuffer commandBuffer = app.getCommandBuffer();
    while (!app.shouldClose())
    {
        vkWaitForFences(app.getDevice(), 1, &waitFence, VK_TRUE, UINT64_MAX);
        vkResetFences(app.getDevice(), 1, &waitFence);

        uint32_t imageIndex = 0;
        VkResult result = vkAcquireNextImageKHR(app.getDevice(), app.getSwapchain(), UINT64_MAX,
                                                waitNextImage, VK_NULL_HANDLE, &imageIndex);
        switch (result)
        {
        case VK_SUCCESS:
            printf("Next image: %d\n", imageIndex); break;
        default:
            printf("Next image: %d (RESULT = %d)\n", imageIndex, result);
            app.setClosed(); break;
        }

        VkCommandBufferBeginInfo beginInfo
        {
            VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
            nullptr, 0, nullptr
        };
        vkResetCommandBuffer(commandBuffer, 0);
        vkBeginCommandBuffer(commandBuffer, &beginInfo);
        {
            VkClearValue clearColor = { {0.2f, 0.2f, 0.4f, 1.0f} };
            VkRenderPassBeginInfo renderPassInfo
            {
                VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
                nullptr, renderPass,
                framebuffers[imageIndex],
                { {0, 0}, {1024, 768} },
                1, &clearColor
            };
            vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
            // TODO
            vkCmdEndRenderPass(commandBuffer);
        }
        vkEndCommandBuffer(commandBuffer);

        app.submitAndPresent(waitNextImage, waitSubmission, waitFence, imageIndex);
        glfwPollEvents();
    }

    for (size_t i = 0; i < framebuffers.size(); ++i)
        vkDestroyFramebuffer(app.getDevice(), framebuffers[i], nullptr);
    vkDestroyRenderPass(app.getDevice(), renderPass, nullptr);
    return 0;
}